package testview.zhen.com.myapplication.hencoder.practice_draw1

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.os.Build
import androidx.annotation.RequiresApi
import android.util.AttributeSet
import android.view.View

class Practice9DrawPathView : View {

    constructor(context: Context) : super(context) {}

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        var path:Path = Path()
        var paint:Paint = Paint()



        // Path  的第一类方法：直接描述路径的

        //画一个爱心
        path.addArc(200.0f, 200.0f, 400.0f, 400.0f, -225.0f, 225.0f)
        path.arcTo(400.0f, 200.0f, 600.0f, 400.0f, -180.0f, 225.0f, false)
        path.lineTo(400.0f, 542.0f)

        //画一个圆
//        path.addCircle(300.0f,300.0f,200.0f,Path.Direction.CW)

        //画一条线
//        paint.style = Paint.Style.STROKE
//        path.lineTo(100.0f,100.0f);// 由当前位置 (0, 0) 向 (100, 100) 画一条直线
//        path.rLineTo(100.0f, 0.0f); // 由当前位置 (100, 100) 向正右方 100 像素的位置画一条直线

        //画曲线
//        paint.style = Paint.Style.STROKE
//        path.quadTo(100.0f,100.0f,200.0f,200.0f)//画贝塞尔曲线

        //不论是直线还是贝塞尔曲线，都是以当前位置作为起点，而不能指定起点。
        // 但你可以通过 moveTo(x, y) 或 rMoveTo() 来改变当前位置，从而间接地设置这些方法的起点。
//        paint.style = Paint.Style.STROKE
//        path.lineTo(100.0f,100.0f)// 由当前位置 (0, 0) 向 (100, 100) 画一条直线
//        path.moveTo(200.0f,100.0f)// 将结束的点 移动x轴200.0f,y轴200.0f
//        path.lineTo(200.0f, 0.0f) // 然后画竖线
//        path.moveTo(0.0f,0.0f)  //将点移到（0,0）
//        path.lineTo(400.0f,200.0f) //从（0,0）->（400,200）

        //arcTo() 和 addArc()。它们也是用来画线的，但并不使用当前位置作为弧线的起点。
        // useCenter 参数是指要不要 true「抬一下笔移动过去」，还是 false「直接拖着笔过去」，区别在于是否留下移动的痕迹。
//        paint.style = Paint.Style.STROKE
//        path.lineTo(100.0f,100.0f)
//        path.arcTo(100.0f,100.0f,300.0f,300.0f,0.0f,300.0f,true)

        //close() 封闭当前子图形
//        paint.style = Paint.Style.STROKE
//        path.moveTo(100.0f, 100.0f)
//        path.lineTo(200.0f, 100.0f)
//        path.lineTo(150.0f, 150.0f)
//        path.close() // 使用 close() 封闭子图形。等价于 path.lineTo(100, 100)
        /**
         * close() 和 lineTo(起点坐标) 是完全等价的。
         * 「子图形」：官方文档里叫做 contour 。但由于在这个场景下我找不到这个词合适的中文翻译（直译的话叫做「轮廓」），所以我换了个便于中国人理解的词：
         * 「子图形」。前面说到，第一组方法是「添加子图形」，所谓「子图形」，指的就是一次不间断的连线。一个 Path 可以包含多个子图形。
         * 当使用第一组方法，即 addCircle() addRect() 等方法的时候，每一次方法调用都是新增了一个独立的子图形；
         * 而如果使用第二组方法，即 lineTo() arcTo() 等方法的时候，则是每一次断线（即每一次「抬笔」），都标志着一个子图形的结束，以及一个新的子图形的开始。
         * 另外，不是所有的子图形都需要使用 close() 来封闭。当需要填充图形时（即 Paint.Style 为 FILL 或 FILL_AND_STROKE），Path 会自动封闭子图形。
         */
        //eg:
//        paint.style = Paint.Style.FILL
//        path.moveTo(100.0f, 100.0f)
//        path.lineTo(200.0f, 100.0f)
//        path.lineTo(150.0f, 150.0f)



        //Path 方法第二类：辅助的设置或计算
        // Path.setFillType(fillType) 是用来设置图形自相交时的填充算法的：
        //EVEN_ODD 奇数原则 两个相交部分为2 没相交的为1 1要填充颜色  「交叉填充」：
        //WINDING （默认值） WINDING 是「全填充」  （非零环绕数原则）
       // 首先，它需要你图形中的所有线条都是有绘制方向的：
        //然后，同样是从平面中的点向任意方向射出一条射线，但计算规则不一样：
        // 以 0 为初始值，对于射线和图形的所有交点，遇到每个顺时针的交点（图形从射线的左边向右穿过）把结果加 1，
        // 遇到每个逆时针的交点（图形从射线的右边向左穿过）把结果减 1，最终把所有的交点都算上，得到的结果如果不是 0，
        // 则认为这个点在图形内部，是要被涂色的区域；如果是 0，则认为这个点在图形外部，是不被涂色的区域。

        //INVERSE_EVEN_ODD
        //INVERSE_WINDING

        canvas.drawPath(path,paint)
        //        练习内容：使用 canvas.drawPath() 方法画心形
    }
}
